home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / libtiff / tools / gif2tiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  12.8 KB  |  514 lines

  1. /* $Header: /usr/people/sam/tiff/tools/RCS/gif2tiff.c,v 1.27 1996/04/22 22:03:26 sam Rel $ */
  2.  
  3. /*
  4.  * Copyright (c) 1990-1996 Sam Leffler
  5.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  *    convert a GIF file into a TIFF file.
  29.  *    based on Paul Haeberli's fromgif program which in turn is
  30.  *    based on a GIF file reader by Marcel J.E. Mol March 23 1989 
  31.  *
  32.  *    if input is 320 by 200 pixel aspect is probably 1.2
  33.  *    if input is 640 350 pixel aspect is probably 1.37
  34.  *
  35.  */
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <math.h>
  40.  
  41. #include "tiffio.h"
  42.  
  43. #if defined(_WINDOWS) || defined(MSDOS)
  44. #define BINMODE "b"
  45. #else
  46. #define    BINMODE
  47. #endif
  48.  
  49. #define    GIFGAMMA    (1.5)        /* smaller makes output img brighter */
  50. #define    IMAX        0xffff        /* max intensity value */
  51. #define EXTRAFUDGE    128        /* some people write BAD .gif files */
  52.  
  53. #define    streq(a,b)    (strcmp(a,b) == 0)
  54. #define    strneq(a,b,n)    (strncmp(a,b,n) == 0)
  55.  
  56. unsigned short gamtab[256];
  57.  
  58. void
  59. makegamtab(float gam)
  60. {
  61.     int i;
  62.  
  63.     for(i=0; i<256; i++) 
  64.     gamtab[i] = IMAX*pow(i/255.0,gam)+0.5;
  65. }
  66.  
  67. char* stuff[] = {
  68. "usage: gif2tiff [options] input.gif output.tif",
  69. "where options are:",
  70. " -r #        make each strip have no more than # rows",
  71. "",
  72. " -c lzw[:opts]    compress output with Lempel-Ziv & Welch encoding",
  73. " -c zip[:opts]    compress output with deflate encoding",
  74. " -c packbits    compress output with packbits encoding",
  75. " -c none    use no compression algorithm on output",
  76. "",
  77. "LZW and deflate options:",
  78. " #        set predictor value",
  79. "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
  80. NULL
  81. };
  82.  
  83. static void
  84. usage(void)
  85. {
  86.     char buf[BUFSIZ];
  87.     int i;
  88.  
  89.     setbuf(stderr, buf);
  90.     for (i = 0; stuff[i] != NULL; i++)
  91.         fprintf(stderr, "%s\n", stuff[i]);
  92.     exit(-1);
  93. }
  94.  
  95. #define COLSIZE 256
  96.  
  97. unsigned char *stackp;
  98. unsigned int prefix[4096];
  99. unsigned char suffix[4096];
  100. unsigned char stack[4096];
  101. int datasize,codesize,codemask;     /* Decoder working variables */
  102. int clear,eoi;                      /* Special code values */
  103. int avail, oldcode;
  104.  
  105. FILE *infile;
  106. int global;                        /* Is there a global color map? */
  107. int globalbits;                     /* Number of bits of global colors */
  108. unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
  109. unsigned char *raster;              /* Decoded image data */
  110. unsigned long width, height;
  111. unsigned short red[COLSIZE];
  112. unsigned short green[COLSIZE];
  113. unsigned short blue[COLSIZE];
  114. char *filename, *imagename;
  115.  
  116. static    uint16 compression = COMPRESSION_LZW;
  117. static    uint16 predictor = 0;
  118. static    uint32 rowsperstrip = (uint32) -1;
  119. static    int processCompressOptions(char*);
  120.  
  121. int    convert(void);
  122. int    checksignature(void);
  123. void    readscreen(void);
  124. int    readgifimage(char*);
  125. void    readextension(void);
  126. int    readraster(void);
  127. int    process(int, unsigned char**);
  128. void    initcolors(unsigned char [COLSIZE][3], int);
  129. void    rasterize(int, char*);
  130.  
  131. int
  132. main(int argc, char* argv[])
  133. {
  134.     extern int optind;
  135.     extern char *optarg;
  136.     int c, status;
  137.  
  138.     while ((c = getopt(argc, argv, "c:r:")) != -1)
  139.         switch (c) {
  140.         case 'c':        /* compression scheme */
  141.             if (!processCompressOptions(optarg))
  142.                 usage();
  143.             break;
  144.         case 'r':        /* rows/strip */
  145.             rowsperstrip = atoi(optarg);
  146.             break;
  147.         case '?':
  148.             usage();
  149.             /*NOTREACHED*/
  150.         }
  151.     if (argc - optind != 2)
  152.         usage();
  153.  
  154.     makegamtab(GIFGAMMA);
  155.     filename = argv[optind];
  156.     imagename = argv[optind+1];
  157.     if ((infile = fopen(imagename, "r" BINMODE)) != NULL) {
  158.     int c;
  159.     fclose(infile);
  160.     printf("overwrite %s? ", imagename); fflush(stdout);
  161.     c = getc(stdin);
  162.     if (c != 'y' && c != 'Y')
  163.         return (1);
  164.     }
  165.     if ((infile = fopen(filename, "r" BINMODE)) == NULL) {
  166.     perror(filename);
  167.     return (1);
  168.     }
  169.     status = convert();
  170.     fclose(infile);
  171.     return (status);
  172. }
  173.  
  174. static int
  175. processCompressOptions(char* opt)
  176. {
  177.     if (streq(opt, "none"))
  178.         compression = COMPRESSION_NONE;
  179.     else if (streq(opt, "packbits"))
  180.         compression = COMPRESSION_PACKBITS;
  181.     else if (strneq(opt, "lzw", 3)) {
  182.         char* cp = strchr(opt, ':');
  183.         if (cp)
  184.             predictor = atoi(cp+1);
  185.         compression = COMPRESSION_LZW;
  186.     } else if (strneq(opt, "zip", 3)) {
  187.         char* cp = strchr(opt, ':');
  188.         if (cp)
  189.             predictor = atoi(cp+1);
  190.         compression = COMPRESSION_DEFLATE;
  191.     } else
  192.         return (0);
  193.     return (1);
  194. }
  195.  
  196. int
  197. convert(void)
  198. {
  199.     int ch;
  200.     char* mode = "w";
  201.  
  202.     if (!checksignature())
  203.         return (-1);
  204.     readscreen();
  205.     while ((ch = getc(infile)) != ';' && ch != EOF) {
  206.         switch (ch) {
  207.             case '\0':  break;  /* this kludge for non-standard files */
  208.             case ',':   if (!readgifimage(mode))
  209.                            return (-1);
  210.             mode = "a";        /* subsequent images append */
  211.                         break;
  212.             case '!':   readextension();
  213.                         break;
  214.             default:    fprintf(stderr, "illegal GIF block type\n");
  215.                         return (-1);
  216.         }
  217.     }
  218.     return (0);
  219. }
  220.  
  221. int
  222. checksignature(void)
  223. {
  224.     char buf[6];
  225.  
  226.     fread(buf,1,6,infile);
  227.     if (strncmp(buf,"GIF",3)) {
  228.         fprintf(stderr, "file is not a GIF file\n");
  229.         return 0;
  230.     }
  231.     if (strncmp(&buf[3],"87a",3)) {
  232.         fprintf(stderr, "unknown GIF version number\n");
  233.         return 0;
  234.     }
  235.     return 1;
  236. }
  237.  
  238. /*
  239.  *     readscreen - 
  240.  *        Get information which is global to all the images stored 
  241.  *    in the file
  242.  */
  243. void
  244. readscreen(void)
  245. {
  246.     unsigned char buf[7];
  247.  
  248.     fread(buf,1,7,infile);
  249.     global = buf[4] & 0x80;
  250.     if (global) {
  251.         globalbits = (buf[4] & 0x07) + 1;
  252.         fread(globalmap,3,1<<globalbits,infile);
  253.     }
  254. }
  255.  
  256. int
  257. readgifimage(char* mode)
  258. {
  259.     unsigned char buf[9];
  260.     int local, interleaved;
  261.     unsigned char localmap[256][3];
  262.     int localbits;
  263.     int status;
  264.  
  265.     if (fread(buf, 1, 9, infile) == 0) {
  266.         perror(filename);
  267.     return (0);
  268.     }
  269.     width = buf[4] + (buf[5] << 8);
  270.     height = buf[6] + (buf[7] << 8);
  271.     local = buf[8] & 0x80;
  272.     interleaved = buf[8] & 0x40;
  273.  
  274.     if (local == 0 && global == 0) {
  275.         fprintf(stderr, "no colormap present for image\n");
  276.         return (0);
  277.     }
  278.     if ((raster = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
  279.         fprintf(stderr, "not enough memory for image\n");
  280.         return (0);
  281.     }
  282.     if (local) {
  283.         localbits = (buf[8] & 0x7) + 1;
  284.  
  285.         fprintf(stderr, "   local colors: %d\n", 1<<localbits);
  286.  
  287.         fread(localmap, 3, 1<<localbits, infile);
  288.         initcolors(localmap, 1<<localbits);
  289.     } else if (global) {
  290.         initcolors(globalmap, 1<<globalbits);
  291.     }
  292.     if (status = readraster())
  293.     rasterize(interleaved, mode);
  294.     _TIFFfree(raster);
  295.     return status;
  296. }
  297.  
  298. /*
  299.  *     readextension -
  300.  *        Read a GIF extension block (and do nothing with it).
  301.  *
  302.  */
  303. void
  304. readextension(void)
  305. {
  306.     int count;
  307.     char buf[255];
  308.  
  309.     (void) getc(infile);
  310.     while (count = getc(infile))
  311.         fread(buf, 1, count, infile);
  312. }
  313.  
  314. /*
  315.  *     readraster -
  316.  *        Decode a raster image
  317.  *
  318.  */
  319. int
  320. readraster(void)
  321. {
  322.     unsigned char *fill = raster;
  323.     unsigned char buf[255];
  324.     register int bits=0;
  325.     register unsigned long datum=0;
  326.     register unsigned char *ch;
  327.     register int count, code;
  328.     int status = 1;
  329.  
  330.     datasize = getc(infile);
  331.     clear = 1 << datasize;
  332.     eoi = clear + 1;
  333.     avail = clear + 2;
  334.     oldcode = -1;
  335.     codesize = datasize + 1;
  336.     codemask = (1 << codesize) - 1;
  337.     for (code = 0; code < clear; code++) {
  338.     prefix[code] = 0;
  339.     suffix[code] = code;
  340.     }
  341.     stackp = stack;
  342.     for (count = getc(infile); count > 0; count = getc(infile)) {
  343.     fread(buf,1,count,infile);
  344.     for (ch=buf; count-- > 0; ch++) {
  345.         datum += (unsigned long) *ch << bits;
  346.         bits += 8;
  347.         while (bits >= codesize) {
  348.         code = datum & codemask;
  349.         datum >>= codesize;
  350.         bits -= codesize;
  351.         if (code == eoi) {               /* This kludge put in */
  352.             goto exitloop;               /* because some GIF files*/
  353.         }                                /* aren't standard */
  354.         if (!process(code, &fill)) {
  355.             status = 0;
  356.             goto exitloop;
  357.         }
  358.         }
  359.     }
  360.     if (fill >= raster + width*height) {
  361.         fprintf(stderr, "raster full before eoi code\n");
  362.         break;
  363.     }
  364.     }
  365. exitloop:
  366.     if (fill != raster + width*height)  {
  367.     fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
  368.                               (long) (fill-raster));
  369.     fprintf(stderr, "         instead of %ld bytes\n",
  370.                               (long) width*height);
  371.     }
  372.     return status;
  373. }
  374.  
  375. /*
  376.  *     process - 
  377.  *        Process a compression code.  "clear" resets the code table.  
  378.  *    Otherwise make a new code table entry, and output the bytes 
  379.  *    associated with the code.
  380.  */
  381. int
  382. process(register int code, unsigned char** fill)
  383. {
  384.     int incode;
  385.     static unsigned char firstchar;
  386.  
  387.     if (code == clear) {
  388.     codesize = datasize + 1;
  389.     codemask = (1 << codesize) - 1;
  390.     avail = clear + 2;
  391.     oldcode = -1;
  392.     return 1;
  393.     }
  394.  
  395.     if (oldcode == -1) {
  396.     *(*fill)++ = suffix[code];
  397.     firstchar = oldcode = code;
  398.     return 1;
  399.     }
  400.     if (code > avail) {
  401.     fprintf(stderr, "code %d too large for %d\n", code, avail);
  402.     return 0; 
  403.     }
  404.  
  405.     incode = code;
  406.     if (code == avail) {      /* the first code is always < avail */
  407.     *stackp++ = firstchar;
  408.     code = oldcode;
  409.     }
  410.     while (code > clear) {
  411.     *stackp++ = suffix[code];
  412.     code = prefix[code];
  413.     }
  414.  
  415.     *stackp++ = firstchar = suffix[code];
  416.     prefix[avail] = oldcode;
  417.     suffix[avail] = firstchar;
  418.     avail++;
  419.  
  420.     if (((avail & codemask) == 0) && (avail < 4096)) {
  421.     codesize++;
  422.     codemask += avail;
  423.     }
  424.     oldcode = incode;
  425.     do {
  426.     *(*fill)++ = *--stackp;
  427.     } while (stackp > stack);
  428.     return 1;
  429. }
  430.  
  431. /*
  432.  *     initcolors -
  433.  *        Convert a color map (local or global) to arrays with R, G and B
  434.  *     values. 
  435.  *
  436.  */
  437. void
  438. initcolors(unsigned char colormap[COLSIZE][3], int ncolors)
  439. {
  440.     register int i;
  441.  
  442.     for (i = 0; i < ncolors; i++) {
  443.         red[i]   = gamtab[colormap[i][0]];
  444.         green[i] = gamtab[colormap[i][1]];
  445.         blue[i]  = gamtab[colormap[i][2]];
  446.     }
  447. }
  448.  
  449. void
  450. rasterize(int interleaved, char* mode)
  451. {
  452.     register long row;
  453.     register unsigned char *rr;
  454.     unsigned char *newras;
  455.     TIFF *tif;
  456.     tstrip_t strip;
  457.     tsize_t stripsize;
  458.  
  459.     if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
  460.         fprintf(stderr, "not enough memory for image\n");
  461.         return;
  462.     }
  463. #define DRAWSEGMENT(offset, step) {            \
  464.     register unsigned char* ras = raster;        \
  465.         for (row = offset; row < height; row += step) {    \
  466.             rr = newras + row*width;            \
  467.             _TIFFmemcpy(rr, ras, width);        \
  468.             ras += width;                                \
  469.         }                        \
  470.     }
  471.     if (interleaved) {
  472.         DRAWSEGMENT(0, 8);
  473.         DRAWSEGMENT(4, 8);
  474.         DRAWSEGMENT(2, 4);
  475.         DRAWSEGMENT(1, 2);
  476.     } else 
  477.         DRAWSEGMENT(0, 1);
  478. #undef DRAWSEGMENT
  479.  
  480.     tif = TIFFOpen(imagename, mode);
  481.     if (!tif) {
  482.     TIFFError(imagename,"Can not open output image");
  483.     exit(-1);
  484.     }
  485.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
  486.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
  487.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
  488.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  489.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
  490.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  491.     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 
  492.     rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip));
  493.     TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
  494.     switch (compression) {
  495.     case COMPRESSION_LZW:
  496.     case COMPRESSION_DEFLATE:
  497.         if (predictor != 0)
  498.             TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
  499.         break;
  500.     }
  501.     TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
  502.     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  503.     strip = 0;
  504.     stripsize = TIFFStripSize(tif);
  505.     for (row=0; row<height; row += rowsperstrip) {
  506.     if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0)
  507.         break;
  508.     strip++;
  509.     }
  510.     TIFFClose(tif);
  511.  
  512.     _TIFFfree(newras);
  513.